local filename = "roomcmd.lua"

local skynet = require "skynet"
local cluster = require "skynet.cluster"
require "skynet.manager"

local servicepoolmng = require "incrservicepoolmng"
local configdao = require "configdao"
local timetool = require "timetool"
local filelog = require "filelog"

require "fishenum"

local CMD = {}
local table_service_map = {}
local index_to_code = {}
local table_list = {publist = {}, mylist = {}}
local robotsnum = {pub = {}, mine = {}}
local router
local service = {
	code_map = {},
	idx = 1,
}
local rolestats = {}
local counter = {
	zijian_diamond = 0,
	game_types = {0, 0, 0, 0},
	all = 0,
}

local distribution = {	-- 系数分布
	-- f1, f2, f3, f4, 
}

-- base configs
local baseshootlevels = {1, 10, 50, 100}
local upgradestages = {1, 10, 10, 100}
local min_carry_diamonds = {300, 2000, 5000, 10000}

-- 生成一个桌子号，随机码
local function gen_table_code(table_index, create_rid, table_conf)
	local newcode = cluster.call("hallnode", ".router", "create_table_code", skynet.getenv("nodename"), table_index, create_rid, table_conf)
	return newcode
end

function CMD.init_table_pool(nodeconf)
	service.idle_table_mng = servicepoolmng:new({}, {service_name = "table", service_size = nodeconf.tablesize, incr=nodeconf.tableinrc})
end

function CMD.update_table_player(idx, game_type, num, is_public)
	if is_public and is_public == 1 then
		table_list.publist[game_type][idx].cur_player = num
	-- else
		-- table_list.mylist[game_type][idx].cur_player = num
	end
end

function CMD.change_robot_num(num, idx, game_type, is_public)
	if is_public and is_public == 1 then
		robotsnum.pub[idx] = (robotsnum.pub[idx] or 0) + num
	-- else
	-- 	robotsnum.mine[idx] = (robotsnum.mine[idx] or 0) + num
	end
end

function CMD.get_table_player(idx)
	if table_list.publist[idx] then
		return table_list.publist[idx].cur_player or 0
	end
end

function CMD.get_table_list()
	return table_list.publist
end

function CMD.get_gamenode_data()
	return table_service_map
end

function CMD.get_gamenode_codes()
	return index_to_code
end

function CMD.getpubtablelist(rid, roledata)
    local list = {matchlist = {}}
	for i, value in ipairs(baseshootlevels) do
		local offset = 0
		-- if i == 3 then offset = 1 end
		list.matchlist[i] = {
			dizhu			= value,
			ruchang		    = min_carry_diamonds[i],--入场钻石
			conf_intro      = {
				game_type = i,
				range_min = value,
				range_max = value + upgradestages[i] * (4 + offset),
			},					--匹配桌配置
			max_player      = 4,					--桌子最大人数                         
		}
	end
	return list
end

local function get_alltableplayers()
	local n = 0
	for _, v in pairs(table_service_map) do
		if v.conf.game_room_type == EGameRoomType.ROOM_TYPE_ZIJIAN_ZUANSI then
			n = n + (skynet.call(v.table_service, "lua", "gettableplayer",  rid, rdata, args) or 0)
		end
	end
	return n
end

function CMD.getgamestate()
	local result = {
        zijian_fangka = counter.zijian_fangka,
        zijian_diamond = get_alltableplayers(),	-- counter.zijian_diamond,
        zijian_coin = counter.zijian_coin,
        match_diamond = counter.match_diamond,
        match_coin = counter.match_coin,
    }
	-- result.match_diamond = result.match_diamond + router.get_playing_player()
	-- result.match_coin = result.match_coin + router.get_playing_player_coin()
	filelog.debug("getgamestate:", counter, result)
	return result
end

--[[游戏房间类型
EGameRoomType = {
    ROOM_TYPE_ZIJIAN_FANGKA = 1,        --自建房卡房
    ROOM_TYPE_ZIJIAN_ZUANSI = 2,        --自建钻石房
    ROOM_TYPE_MATCH_ZUANSHI = 3,        --匹配钻石房
    ROOM_TYPE_MATCH_COIN = 4,           --匹配金豆房
    ROOM_TYPE_ZIJIAN_COIN = 5,          --自建金豆房
}
--]]
local function player_counter(gameroomtype, num)
	if gameroomtype == 2 then
		counter.zijian_diamond = counter.zijian_diamond + num
	end
	counter.all = counter.all + num
end

local function game_type_counter(game_type, num)
	counter.game_types[game_type] = counter.game_types[game_type] + num
end

function CMD.getlevellist()
	local responsemsg = {}
	if router.will_kill then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "服务器维护中"
		return responsemsg
	end
	local list = {}
	local i = 1
	for idx, data in pairs(table_list.publist) do
		list[i] = {
			level_type = data.game_type,			--场次类型 1初级 2中级 3高级
			min_carry_amount = data.enter_diamond,	--最小携带量
			max_carry_amount = data.max_diamond,	--最大携带量
			up_banker_money = data.leave_diamond,	--上庄金币数
			conf_intro = data.conf_intro,			--场次桌子配置,json编码字符串
			cur_total_player = data.cur_player,		--当前总人数
		}
		i = i + 1
		if i > 30 then
			break
		end
	end
	--获得匹配场信息
	-- list.matchlist = router.get_matchlist()
	responsemsg.levellist = list
	return responsemsg
end

function CMD.createtable(rid, rdata, args)
	-- filelog.sys_error("createtable ======>>>", args)
	local responsemsg = {}
	if router.will_kill then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "服务器维护中"
		return responsemsg
	end
	if rolestats[rid] then
		filelog.sys_error("CMD.createfriendtable creating!")
		return
	end
	rolestats[rid] = 1
	local role_data = router.get_role_data(rid)
	if role_data and rdata.info.level ~= 99 then
		rolestats[rid] = nil
		return
	end
	local game_type = args.config.mode or args.config.game_type or EGameType.GAME_TYPE_NORMAL
	local conf = {
		room_type = ERoomType.ROOM_TYPE_COMMON,
		game_room_type = EGameRoomType.ROOM_TYPE_ZIJIAN_ZUANSI,
		name = rdata.info.rolename .. "的房间",
		game_type = game_type,
		max_player_num = 4,	--最大玩家数
		is_public = 1,
		min_player_num = 1,	-- 最少玩家数
	    create_user_rid = rid,
	    create_user_name = rdata.info.rolename,
	    create_user_logo = rdata.info.logo,
	    create_time = timetool.get_time(),
		min_carry_diamond = min_carry_diamonds[game_type],
		leave_carry_diamond = 0,
		max_carry_diamond = 0,
		rid = rid,
		retain_time = 60,	-- rdata.table_persist or 1,	-- 桌子保留时间
		max_watch_playernum = 0,
		baseshootlevel = baseshootlevels[game_type] or 5,
		upgradestage = upgradestages[game_type] or 10,
		-- stageoffset = game_type == 3 and 1 or 0,
		stageoffset = game_type == 3 and 0 or 0,
	}

	if #distribution > 0 then
		conf.distribution = distribution
	end

	local tableservice = service.idle_table_mng:create_service()
	local table_code, table_service, idx
	if tableservice ~= nil then
		--生成随机码
		table_service = tableservice.service
		idx = service.idx
		table_code = gen_table_code(idx, rid, args.config)

		conf.table_code = table_code
		conf.create_time = timetool.get_time()
		conf.idx = idx
		service.code_map[table_code] = true
		local result, msg = skynet.call(table_service, "lua", "start", conf)
		if not result then
			pcall(skynet.kill, table_service)
			service.code_map[table_code] = nil
			responsemsg.retcode = EErrCode.ERR_SYSTEM_ERROR
			responsemsg.retstr = "系统错误，创建失败！"
			filelog.error("CMD.createfriendtable failed!")
			rolestats[rid] = nil
			return responsemsg
		end

		if conf.is_public and conf.is_public == 1 then
			table_list.publist[game_type] = table_list.publist[game_type] or {}
			table_list.publist[game_type][idx] = {
				table_index		= idx,
				table_code		= table_code,
				enter_diamond	= conf.min_carry_diamond,
				leave_diamond	= conf.leave_carry_diamond,
				conf_intro		= {game_type = game_type},
				max_player		= conf.max_player_num,
				cur_player		= 0,
				create_time		= conf.create_time,
			}
		end

		service.idx = service.idx + 1
	else
		filelog.sys_error("CMD:createtable roomsvr's idle_table_mng has no enough tableservice!")
		responsemsg.retcode = EErrCode.ERR_SYSTEM_ERROR
		responsemsg.retstr = "系统错误，创建房间失败！"
		rolestats[rid] = nil
		return responsemsg
	end

	responsemsg.table_index = idx
	table_service_map[table_code] = {
		table_index = idx,
		table_service = table_service,
		game_type = game_type,
		game_room_type = conf.game_room_type,
	}
	index_to_code[idx] = table_code
	rolestats[rid] = nil
    return responsemsg
end

function CMD.entertable(rid, rdata, args)
	-- filelog.sys_error("entertable ======>>>", args)
	local responsemsg = {}
	if router.will_kill then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "服务器维护中"
		return responsemsg
	end
	if rolestats[rid] then
		-- filelog.sys_error("CMD.entertable entering!")
		return
	end
	
	local role_data = router.get_role_data(rid)
	if role_data then
		-- filelog.sys_error("CMD.entertable: 玩家进桌状态异常！")
		return
	end

	if counter.all >= 160 then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "人数已经满了！"
		return responsemsg
	end

	args.level_type = args.level_type or EGameType.GAME_TYPE_NORMAL
	if args.level_type <= 0 then args.level_type = EGameType.GAME_TYPE_NORMAL end
	-- 按类别寻找未满的房间
	local table_index = args.table_index
	if not table_index or table_index <= 0 then
		for k, v in pairs(table_list.publist[args.level_type] or {}) do
			if v.cur_player < v.max_player then
				table_index = k
				break
			end
		end
	end
	-- 没有找到就创建新房间
	if not table_index or table_index <= 0 then
		table_index = CMD.createtable(rid, rdata, {config = {game_type = args.level_type}}).table_index
	end
	if not table_index or table_index <= 0 then
		responsemsg.retcode = EErrCode.ERR_SYSTEM_ERROR
		responsemsg.retstr = "没有找到桌子！"
		filelog.sys_error("CMD.entertable: 创建房间失败!")
		return responsemsg
	end

	rolestats[rid] = 1
	local code = index_to_code[table_index]
	if not code or not table_service_map[code] then
		responsemsg.retcode = EErrCode.ERR_INVALID_PARAMS
		responsemsg.retstr = "没有找到桌子！"
		filelog.sys_error("CMD.entertable: 没有找到桌子！")
	else
		local game_room_type = table_service_map[code].game_room_type
		local table_service = table_service_map[code].table_service
		local table_index = table_service_map[code].table_index
		local ok, result = pcall(skynet.call, table_service, "lua", "entertable", rid, rdata, args)
		if ok then
			responsemsg = result
			if not result.retcode or result.retcode == 0 then
				router.forward(rid, table_service, table_index)
				if rdata.info.level ~= 99 then
					player_counter(game_room_type, 1)
				end
				game_type_counter(args.level_type, 1)
			end
		else
			responsemsg.retcode = EErrCode.ERR_INVALID_PARAMS
			responsemsg.retstr = "没有找到桌子！"
			filelog.sys_error("CMD.entertable: 桌子已经不存在！", result)
		end
	end
	rolestats[rid] = nil
	return responsemsg
end

function CMD.reentertable(rid, rdata, args)
	local responsemsg = {}
	local role_data = router.get_role_data(rid)
	if not role_data or not role_data.table_service then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "没有找到桌子！"
		router.unforward(rid, args.table_index)
	else
		local table_service = role_data.table_service
		local ok, result = pcall(skynet.call, table_service, "lua", "reentertable", rid, rdata, args)
		if not ok then
			responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
			responsemsg.retstr = "没有找到桌子！"
		else
			responsemsg = result
		end
		if responsemsg then
			if responsemsg.retcode and responsemsg.retcode ~= 0 then
				router.unforward(rid, args.table_index)
			else
				router.forward(rid, table_service, role_data.table_index)
			end
		end
	end
	return responsemsg
end

function CMD.entermatchtable(rid, rdata, args)
	CMD.entertable(rid, rdata, {level_type = args.match_type})
	return {timeout_time = timetool.get_time() + 300}
end

function CMD.rid_change_diamond(rid, begindiamond, value, enddiamond)
	local role_data = router.get_role_data(rid)
	if not role_data or not role_data.table_service then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "玩家没在游戏中！"
	else
		local table_service = role_data.table_service
		skynet.send(table_service, "lua", "rid_change_diamond", rid, begindiamond, value, enddiamond)
	end
end

function CMD.get_alltableinfo()
	local responsemsg = {
		pub_tableinfos = {},
		pub_playerinfos = counter.game_types,
	}
	
	for type, typedata in pairs(table_list.publist) do
		for idx, data in pairs(typedata) do
			responsemsg.pub_tableinfos[idx] = {
				table_index 	= idx,
				enter_diamond	= data.enter_diamond,
				leave_diamond	= data.leave_diamond,
				max_player		= data.max_player,
				cur_player		= data.cur_player,
				robot_num		= robotsnum.pub[idx] or 0,
				game_type		= type,
			}
		end
	end
	-- filelog.debug("get_alltableinfo:", responsemsg)
	return responsemsg
end

function CMD.delete(table_code)
	local idx, game_type
	if table_service_map[table_code] then
		local table_service = table_service_map[table_code].table_service
		idx = table_service_map[table_code].table_index
		game_type = table_service_map[table_code].game_type
		table_service_map[table_code] = nil
		index_to_code[idx] = nil
		skynet.send(table_service, "lua", "exit_service")
		cluster.send("hallnode", ".router", "del_table_code", table_code, skynet.getenv("nodename"), idx)
	end
	if idx and game_type then
		table_list.publist[game_type][idx] = nil
		-- table_list.mylist[game_type][idx] = nil
	end
end

function CMD.destroytable(table_code, table_index)
	if table_service_map[table_code] then
		local table_service = table_service_map[table_code].table_service
		skynet.send(table_service, "lua", "leaveallplayers")
	end
end

function CMD.playerleavetable(rid, game_room_type, isrobot, game_type)
	if rid then
		router.unforward(rid)
		if not isrobot then	-- 没有统计机器人
			player_counter(game_room_type, -1)
		end
		game_type_counter(game_type, -1)
	end
end

function CMD.set_gameend_flag()
	router.will_kill = true
	for k, v in pairs(table_service_map) do
		skynet.send(v.table_service, "lua", "kill")
	end
end

function CMD.set_tableend_flag(code)
	return true
end

function CMD.clear_player_state(rid)
	router.unforward(rid)
end

function CMD.update_distribution(data, table_code)
	if type(data) ~= type{} then return end
	if table_code then
		if table_service_map[table_code] then
			skynet.send(table_service_map[table_code].table_service, "lua", "updatedistribution", {data = data})
		end
	else
		for i, v in ipairs(data) do
			distribution[i] = data[i]
		end
		for k, v in pairs(table_service_map) do
			skynet.send(v.table_service, "lua", "updatedistribution", {data = data})
		end
	end
end

--[[
local robotscheduler = require("fishscheduler")

function CMD.get_schedule_stat()
	return robotscheduler.get_robot_stat()
end

function CMD.change_schedule_state(newstat)
	robotscheduler.change_schedule_state(newstat)
end
--]]

local robotmgr = require "robotmgr"
function CMD.init(base)
	router = base
	-- robotscheduler.init(base)
	-- robotscheduler.change_schedule_state(true)

	-- robotmgr.change_robot_state(true)
end

return CMD